home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / program / freeli20.zip / freelib.doc < prev    next >
Text File  |  1996-07-01  |  69KB  |  2,326 lines

  1. o─────────────────────────────────────────────────────────────────o
  2. │────────── FREELIB: The FREE Assembly Language Library ──────────│
  3. │────────────────────────── Version 2.0 ──────────────────────────│
  4. │───────────── Copyright (C) July 1996 Tenie Remmel ──────────────│
  5. o─────────────────────────────────────────────────────────────────o
  6.  
  7. 1. Introduction ................................ Line 34
  8. 2. Terms of use/Legal disclaimer ............... Line 53
  9. 3. Processors, calling conventions ............. Line 74
  10. 4. Re-assembling ............................... Line 140
  11. 5. Program Syntax .............................. Line 169
  12. 6. Procedure Reference ......................... Line 242
  13.     Initialization and Exit .................... Line 244
  14.     File Access ................................ Line 268
  15.     Directory and Disk ......................... Line 414
  16.     Bit-File Access ............................ Line 482
  17.     Memory Management .......................... Line 593
  18.     String Input/Output ........................ Line 658
  19.     Formatted Output ........................... Line 738
  20.     Alphanumeric Conversion .................... Line 830
  21.     Long/Fixed-Point Arithmetic ................ Line 922
  22.     Trigonometry ............................... Line 1067
  23.     String Manipulation ........................ Line 1138
  24.     Memory-Block Manipulation .................. Line 1255
  25.     Searches and Sorts ......................... Line 1307
  26.     Miscellaneous .............................. Line 1417
  27.     High-Res Text Mode ......................... Line 1563
  28.     VGA Graphics ............................... Line 1980
  29. 7. List of contributors ........................ Line 2173
  30. 8. History of changes .......................... Line 2188
  31. 9. Future additions, bug reporting ............. Line 2257
  32. 10. Example programs ........................... Line 2291
  33.  
  34.  
  35. 1.  Introduction.
  36.  
  37.   FREELIB is a library of 171 procedures that may be useful for
  38.   programming in assembly language.   As the name implies, this
  39.   is public domain, completely free for all non-commercial use.
  40.   If you find this library useful,  you are strongly encouraged
  41.   to contribute some of your own routines for possible addition
  42.   to FREELIB.  Full source code is included, so if you find any
  43.   bugs (!) and wish to make changes to any of the routines, you
  44.   can.  However, if you do make any improvements, please notify
  45.   the author,  so that FREELIB  can continue to be expanded and
  46.   improved. If you modify any part of this library, you may not
  47.   distribute it, for free or not, without prior permission from
  48.   the author (see below).
  49.  
  50.   Be sure to read the sections 2, 3 and 5 carefully,  including
  51.   the miscellaneous notes in section 3.
  52.  
  53.  
  54. 2.  Terms of use/Legal disclaimer.
  55.  
  56.   This software is hereby released into the public domain,  and
  57.   may  therefore  be freely  copied and distributed  within the
  58.   following restrictions:
  59.  
  60.       1).  It is distributed in its original,  unmodified form,
  61.            including all source code and documentation.
  62.  
  63.       2).  No fee is charged for use, copying or distribution.
  64.  
  65.       3).  The program may not be  included with other goods or
  66.            services supplied for a fee, unless specific written
  67.            permission to do so is obtained  in advance from the
  68.            author. (E-mail: tjr19@mail.nwlink.com)
  69.  
  70.   This program is provided AS-IS without any warranty,  express
  71.   or implied, including  but not limited to warranty of fitness
  72.   for a particular purpose.
  73.  
  74.  
  75. 3.  Processors, calling conventions, string type, etc.
  76.  
  77.   FREELIB is programmed in 80186 assembly language.  This is to
  78.   ensure compatibility with as many computers as possible,  but
  79.   not sacrificing very much speed.  For many of the procedures,
  80.   an 80386 version is supplied.   The modules 386LIB1-2 are the
  81.   80386 versions of FREELIB1-2,  and the 386LIB.LIB file is the
  82.   library file for the 80386.
  83.  
  84.   FREELIB uses the  Pascal calling convention.   The parameters
  85.   are  pushed on the stack in order,  and the calling procedure
  86.   does not have to worry about stack cleanup.  This seems to be
  87.   the fastest method,  and it also helps in debugging... if the
  88.   wrong number of arguments are pushed to call a procedure, the
  89.   program will crash, which is much more obvious than the weird
  90.   results produced with the 'C' convention, etc.
  91.  
  92.   Notice that in the source code,  the syntax is given by a 'C'
  93.   style prototype.  Why a 'C' prototype?  Well, Pascal does not
  94.   have prototypes, and the 'C' prototype is useful to concisely
  95.   show the syntax of a procedure on one line.
  96.  
  97.   Misc. Notes:
  98.  
  99.     Many of the routines assume  DS = CS,  so make sure that this
  100.     is the case.   The program is intended to be a .COM file, but
  101.     .EXE files are OK as long as the DS = CS restriction is met.
  102.  
  103.     Do not use uninitialized data,  it will interfere with memory
  104.     management.  Use dynamically allocated memory instead.
  105.  
  106.     The fixed-point numbers are 16:16,  and signed.   The strings
  107.     are ASCIIZ  (null-terminated) strings,  like in C.   The long
  108.     integers can be either signed or unsigned, depending on which
  109.     multiply, divide and shift you use.
  110.  
  111.     When clock  timings are given,  they will always  include the
  112.     call/return, and exclude the argument pushes.
  113.  
  114.     Even though some  procedures require a character argument,  a
  115.     word-sized value must still be pushed:  it is not possible to
  116.     push a byte value.
  117.  
  118.     The files TEXT???.INC are not to be included in your programs
  119.     as they are internally used by the HighRes Text Mode routines
  120.     in FREELIB3.ASX.
  121.  
  122.     The colorset in High-Res Text Mode is different, see below.
  123.  
  124.     The graphics mode 320x400x256 is a ModeX.   The author of the
  125.     graphics procedures described it as 'dechain mode'.  I assume
  126.     that by this she meant that Chain-4 is off in this mode.
  127.  
  128.   Colorset in High-Res Text Mode:
  129.  
  130.   0 = Black         8 = Dark Gray
  131.   1 = Dark Green    9 = Red
  132.   2 = Green         10 = Orange
  133.   3 = Light Green   11 = Yellow
  134.   4 = True Blue     12 = Sky Blue
  135.   5 = Dark Purple   13 = Dark Blue
  136.   6 = Magenta       14 = Cyan
  137.   7 = Light Gray    15 = White
  138.  
  139.  
  140. 4.  Re-assembling FREELIB.
  141.  
  142.   A batch file (REDO.BAT) is provided for this purpose.   These
  143.   source files are .ASX files (ASsembly eXtended) which contain
  144.   multiple modules.  A utility (SPLIT.EXE) is included to split
  145.   the .ASX files.  SPLIT.C is the 'C' source to SPLIT.EXE.  The
  146.   batch file takes care of splitting the files. However, if you
  147.   wish to add a new .ASX file  (in addition to FREELIB1-3), you
  148.   must modify the batch file, otherwise it will be ignored.
  149.  
  150.   If you wish to  compile the 80386 version,  386LIB,  you must
  151.   use the REDO3.BAT batch file,  and use the  '386LIB*.*' files
  152.   instead of the 'FREELIB*.*' files (except FREELIB3.ASX).
  153.  
  154.   SPLIT outputs TLIB  command file codes.   SPLIT takes zero or
  155.   one arguments.  When run with no arguments, it produces codes
  156.   that end the command file.   When run with an argument  (what
  157.   it is doesn't matter)  it produces codes that continue to the
  158.   next file.
  159.  
  160.   In the .ASX files, a line starting with three tildes (~) that
  161.   are followed by a file name without extension will denote the
  162.   beginning of a new module.   Either make sure that all of the
  163.   module names start with 'C_' or modify the REDO.BAT file.  If
  164.   you put any .ASM  files with names starting with  'C_' in the
  165.   FREELIB directory, be warned: they will be deleted along with
  166.   the temporary .ASM files created by SPLIT.
  167.  
  168.  
  169. 5.  Program syntax for use with FREELIB.
  170.  
  171.   Your program should do a near call, or jump, to the 'startup'
  172.   procedure at the beginning. The main body of the program must
  173.   be in the procedure 'main', which must be declared public.
  174.  
  175.   On entry to main, the number of arguments is in CX and a list
  176.   of near pointers to the arguments is at offset DI.  DS and ES
  177.   both equal CS.  AX, BX, DX, SI, and BP are undefined.
  178.  
  179.   You must declare as  external all procedures  that you intend
  180.   to use.  One way to simplify this is with a macro:
  181.  
  182. ;──────────────────────────────────────
  183.  
  184. Macro       lcall p,a,b,c,d,e,f,g,h ;; library call
  185.  
  186.             ifnb a
  187.               push a                ;; if args, push first arg
  188.               lcall p,b,c,d,e,f,g,h ;; and recurse . . .
  189.             else
  190.               extrn p:near          ;; declare procedure
  191.               call p                ;; call procedure
  192.             endif
  193.  
  194. EndM
  195.  
  196. ;──────────────────────────────────────
  197.  
  198.   and then you would replace  'call' with  'lcall' when calling
  199.   library procedures.   However,  to use the  arguments feature
  200.   of this macro,  if an offset of a variable is used it must be
  201.   specified as 'offset(var)' instead of 'offset var', otherwise
  202.   the macro thinks it is two arguments.
  203.  
  204.   This is a skeleton program:
  205.  
  206. ;──────────────────────────────────────
  207.  
  208. Ideal                               ; ideal mode
  209.  
  210. Public      main                    ; declare main as public
  211. Extrn       startup:near            ; declare startup procedure
  212.  
  213. Macro       lcall p,a,b,c,d,e,f,g,h ;; library call
  214.  
  215.             ifnb a
  216.               push a                ;; if args, push first arg
  217.               lcall p,b,c,d,e,f,g,h ;; and recurse . . .
  218.             else
  219.               extrn p:near          ;; declare procedure
  220.               call p                ;; call procedure
  221.             endif
  222.  
  223. EndM
  224.  
  225. Model Tiny                          ; tiny model
  226. CodeSeg                             ; code segment
  227. Org 100h                            ; .COM file start
  228.  
  229. Start:      jmp startup             ; start up program
  230.  
  231. Proc        main                    ; main procedure
  232.  
  233.             ret                     ; return
  234.  
  235. EndP        main
  236.  
  237. End Start                           ; entry at 'Start'
  238.  
  239. ;──────────────────────────────────────
  240.  
  241.  
  242. 6.  Reference: Syntax and description of all FREELIB procedures.
  243.  
  244.   ─────────────────────────────────────────────────────────────
  245.   ──────────── Initialization and Exit Procedures ─────────────
  246.   ─────────────────────────────────────────────────────────────
  247.  
  248.   ────────── startup            Start program
  249.  
  250.     jmp startup
  251.  
  252.     This procedure must be jumped to at the beginning of
  253.     your program.  (See Section 5.)
  254.  
  255.     This procedure calls 'main'.  It also does internal
  256.     initialization, and sets null Ctrl-C and divide-error
  257.     handlers.
  258.  
  259.   ────────── exit               Exit program
  260.  
  261.     push retcode
  262.     call exit
  263.  
  264.     This procedure exits your program with a return code.
  265.     If exit is not used, the return code is the value of
  266.     AX on return from main.
  267.  
  268.   ─────────────────────────────────────────────────────────────
  269.   ────────────────────── File Procedures ──────────────────────
  270.   ─────────────────────────────────────────────────────────────
  271.  
  272.   ────────── fopen              Open file
  273.  
  274.     push offset filename
  275.     push filemode
  276.     call fopen
  277.     ; AX = handle
  278.  
  279.     This procedure opens a buffered file.  The handle is
  280.     returned in AX.  This handle is NOT a DOS handle.
  281.     If it is used as such, the results are unpredictable.
  282.  
  283.     The file modes are:
  284.  
  285.     0     Open Read-Only (open if it exists, fail if not)
  286.     1     Open/Create (open if it exists, create if not)
  287.     2     Open Only (open if it exists, fail if not)
  288.     3     Create/Truncate (truncate if it exists, create if not)
  289.     4     Create Only (fail if it exists, create if not)
  290.  
  291.   ────────── fclose             Close file
  292.  
  293.     push handle
  294.     call fclose
  295.  
  296.     This procedure closes a buffered file.  If the handle
  297.     is invalid, nothing happens.
  298.  
  299.   ────────── fgetc              Get char from file
  300.  
  301.     push handle
  302.     call fgetc
  303.     ; AX = char
  304.  
  305.     This procedure gets a character from a buffered file.
  306.     If the end of file is reached or an error occurs, -1
  307.     is returned.
  308.  
  309.   ────────── fputc              Put char to file
  310.  
  311.     push handle
  312.     push char
  313.     call fputc
  314.     ; AX = return code
  315.  
  316.     This procedure puts a character to a buffered file.
  317.     If the end of file is reached or an error occurs, -1
  318.     is returned, otherwise the character is returned.
  319.  
  320.   ────────── fread              Read block from file
  321.  
  322.     push handle
  323.     push size
  324.     push offset buf
  325.     call fread
  326.     ; AX = return code
  327.  
  328.     This procedure reads a block from a buffered file.  The
  329.     number of characters read is returned.  If this is less
  330.     than the requested size, the end of file was reached or
  331.     an error occured.
  332.  
  333.   ────────── fwrite             Write block to file
  334.  
  335.     push handle
  336.     push size
  337.     push offset buf
  338.     call fwrite
  339.     ; AX = return code
  340.  
  341.     This procedure writes a block to a buffered file.  The
  342.     number of characters written is returned.  If this is
  343.     less than the requested size, an error occured.
  344.  
  345.   ────────── fseek              Set file pointer
  346.  
  347.     push handle
  348.     push pos_hi
  349.     push pos_lo
  350.     push mode
  351.     call fseek
  352.     ; AX = return code
  353.  
  354.     This procedure sets the position of the file pointer.
  355.     The position is a long integer.  If an error occurs, 0
  356.     is returned, otherwise a nonzero value is returned.
  357.  
  358.     The seek modes are:
  359.  
  360.     0     Seek from beginning of file
  361.     1     Seek from current position
  362.     2     Seek from end of file
  363.  
  364.   ────────── ftell              Get file pointer
  365.  
  366.     push handle
  367.     call ftell
  368.     ; DX:AX = file pointer
  369.  
  370.     This procedure returns the position of the file pointer.
  371.  
  372.   ────────── fsetbuf            Set file buffer size
  373.  
  374.     push size
  375.     call fsetbuf
  376.  
  377.     This procedure sets the file buffer size.  It does not
  378.     affect currently open files.  It only affects files that
  379.     are opened after this call.  The default size is 512
  380.     bytes, but it may be set to from 128 to 32752 bytes.
  381.     If the size requested is greater than 32768, the high
  382.     bit is simply masked off, f.i. 33024 will produce 256.
  383.  
  384.   ────────── ftrunc             Truncate file
  385.  
  386.     push handle
  387.     call ftrunc
  388.     ; AX = return code
  389.  
  390.     This procedure truncates a buffered file at the current
  391.     position.  If an error occurs, 0 is returned, otherwise
  392.     a nonzero value is returned.
  393.  
  394.   ────────── fdel               Delete file
  395.  
  396.     push offset filename
  397.     call fdel
  398.     ; AX = return code
  399.  
  400.     This procedure deletes a file.  If an error occurs, 0 is
  401.     returned, otherwise a nonzero value is returned.
  402.  
  403.   ────────── fmove              Move/Rename file
  404.  
  405.     push offset oldname
  406.     push offset newname
  407.     call fmove
  408.     ; AX = return code
  409.  
  410.     This procedure moves and/or renames a file.  If an error
  411.     occurs, 0 is returned, otherwise a nonzero value is
  412.     returned.
  413.  
  414.   ─────────────────────────────────────────────────────────────
  415.   ─────────────── Directory and Disk Procedures ───────────────
  416.   ─────────────────────────────────────────────────────────────
  417.  
  418.   ────────── mkdir              Create Directory
  419.  
  420.     push offset dirname
  421.     call mkdir
  422.     ; AX = return code
  423.  
  424.     This procedure creates a directory.  If an error occurs,
  425.     0 is returned, otherwise a nonzero value is returned.
  426.  
  427.   ────────── rmdir              Remove Directory
  428.  
  429.     push offset dirname
  430.     call rmdir
  431.     ; AX = return code
  432.  
  433.     This procedure deletes a directory.  If an error occurs,
  434.     0 is returned, otherwise a nonzero value is returned.
  435.  
  436.   ────────── setdir             Set Current Directory
  437.  
  438.     push offset dirname
  439.     call setdir
  440.     ; AX = return code
  441.  
  442.     This procedure sets the current directory.  If an error
  443.     occurs, 0 is returned, otherwise a nonzero value is
  444.     returned.
  445.  
  446.   ────────── getdir             Get Current Directory
  447.  
  448.     push offset buffer
  449.     call getdir
  450.  
  451.     This procedure returns the current directory.
  452.     The full path is returned in 'buffer'.
  453.  
  454.   ────────── setdrive           Set Current Drive
  455.  
  456.     push dr_num
  457.     call setdrive
  458.  
  459.     This procedure sets the current drive.  The numbers are
  460.     the same as the DOS drive numbers.  (0 = default, 1 = A,
  461.     2 = B, 3 = C, etc.)
  462.  
  463.   ────────── getdrive           Get Current Drive
  464.  
  465.     call getdrive
  466.     ; AX = drive number
  467.  
  468.     This procedure returns the current drive.  The numbers
  469.     are the same as the DOS drive numbers.  (0 = default,
  470.     1 = A, 2 = B, 3 = C, etc.)
  471.  
  472.   ────────── getdfree           Get Free Disk Space
  473.  
  474.     push dr_num
  475.     call getdfree
  476.     ; DX:AX = amount of free space
  477.  
  478.     This procedure returns the amount of free disk space
  479.     on a drive.  The number returned is in bytes.
  480.  
  481.  
  482.   ─────────────────────────────────────────────────────────────
  483.   ─────────────── Bit-Oriented File Procedures ────────────────
  484.   ─────────────────────────────────────────────────────────────
  485.  
  486.   ────────── bfopen             Open Bit-File
  487.  
  488.     push offset filename
  489.     push filemode
  490.     call bfopen
  491.     ; AX = handle
  492.  
  493.     This procedure opens a bit-oriented file.  The handle
  494.     is returned in AX.  This handle is NOT a DOS handle, or
  495.     a standard FREELIB handle.  If it is used as such, the
  496.     results are unpredictable.
  497.  
  498.     Bit-oriented files are useful for many compression and
  499.     encryption methods, and simply to reduce space, say, by
  500.     writing 9 bits each for data that ranges from 0 to 500
  501.     instead of using a word (16 bits) to store it.
  502.  
  503.     The file modes are:
  504.  
  505.     0     Open Input Bit File (read-only)
  506.     1     Open Output Bit File (write-only)
  507.  
  508.   ────────── bfclose            Close Bit-File
  509.  
  510.     push handle
  511.     call bfclose
  512.  
  513.     This procedure closes a bit-oriented file.
  514.  
  515.   ────────── getbit             Get Bit from Bit-File
  516.  
  517.     push handle
  518.     call getbit
  519.     ; AX = bit (0 or 1)
  520.  
  521.     This procedure returns the next bit from a bit-oriented
  522.     file in input mode.  The bit is returned in AX.  If the
  523.     file is in output mode, nothing happens, but the return
  524.     value is undefined.
  525.  
  526.   ────────── putbit             Put Bit to Bit-File
  527.  
  528.     push handle
  529.     push bit
  530.     call putbit
  531.  
  532.     This procedure outputs a bit to a bit-oriented file in
  533.     output mode.  The bit is considered a 0 if the number is
  534.     zero, otherwise it is considered a 1.  If the file is in
  535.     input mode, nothing happens.
  536.  
  537.   ────────── getbits            Get Bits from Bit-File
  538.  
  539.     push handle
  540.     push count
  541.     call getbits
  542.     ; AX = value
  543.  
  544.     This procedure inputs a value of size 'count' bits from
  545.     a bit-oriented file.  The value is returned in AX.  If
  546.     the file is in output mode, nothing happens, but the
  547.     return value is undefined.
  548.  
  549.   ────────── putbits            Put Bits to Bit-File
  550.  
  551.     push handle
  552.     push value
  553.     push count
  554.     call putbits
  555.  
  556.     This procedure outputs the low 'count' bits of 'value'
  557.     to a bit-oriented file.  The bits are output in order
  558.     from MSB to LSB.  If the file is in input mode, nothing
  559.     happens.
  560.  
  561.   ────────── getcode            Get Code from Bit-File
  562.  
  563.     push handle
  564.     push max
  565.     call getcode
  566.     ; AX = value
  567.  
  568.     This procedure inputs an optimal binary code for a value
  569.     less than 'max' from a bit-oriented file.  The value is
  570.     returned in AX.  If the file is in output mode, nothing
  571.     happens, but the return value is undefined.  If 'max' is
  572.     specified as 0 or 1, the results will be unpredictable.
  573.  
  574.     An optimal binary code saves a bit versus the standard
  575.     one for some values.  It can be useful for saving space.
  576.  
  577.   ────────── putcode            Put Code to Bit-File
  578.  
  579.     push handle
  580.     push value
  581.     push max
  582.     call putcode
  583.  
  584.     This procedure outputs the optimal binary code for a
  585.     value less than 'max' to a bit-oriented file.  If the
  586.     file is in input mode, nothing happens.  If 'max' is
  587.     specified as 0 or 1, the results will be unpredictable.
  588.  
  589.     An optimal binary code saves a bit versus the standard
  590.     one for some values.  It can be useful for saving space.
  591.  
  592.  
  593.   ─────────────────────────────────────────────────────────────
  594.   ───────────────── Memory Manager Procedures ─────────────────
  595.   ─────────────────────────────────────────────────────────────
  596.  
  597.   ────────── allocmem           Allocate Memory
  598.  
  599.     push size
  600.     call allocmem
  601.     ; AX = pointer
  602.  
  603.     This procedure allocates memory.  If there was not a big
  604.     enough block of memory, -1 is returned, otherwise a
  605.     pointer to the block of memory is returned.
  606.  
  607.   ────────── freemem            Free Memory
  608.  
  609.     push ptr
  610.     call freemem
  611.  
  612.     This procedure frees memory.  If 'ptr' does not point to
  613.     a valid block, nothing happens.  If free blocks abut the
  614.     block to be freed, they are coalesced.
  615.  
  616.   ────────── getmfree           Get Free Memory
  617.  
  618.     call getmfree
  619.     ; AX = size of largest free block
  620.  
  621.     This procedure returns the size of the largest free
  622.     block of memory.  If there are no free blocks, 0 is
  623.     returned.
  624.  
  625.   ────────── faralloc           Allocate Far Memory
  626.  
  627.     push size
  628.     call faralloc
  629.     ; AX = segment
  630.  
  631.     This procedure allocates far memory.  If there was not
  632.     a big enough block of memory, -1 is returned, otherwise
  633.     the segment of the memory block is returned.  The size
  634.     must be specified in paragraphs (16 bytes each).  This
  635.     calls the DOS allocate memory service.
  636.  
  637.   ────────── farfree            Free Far Memory
  638.  
  639.     push seg
  640.     call freemem
  641.  
  642.     This procedure frees far memory.  If 'seg' is not the
  643.     segment of a valid memory block, the results will be
  644.     undefined.  If free blocks abut the block to be freed,
  645.     they are coalesced.  This calls the DOS free memory
  646.     service.
  647.  
  648.   ────────── getfarfree         Get Free Far Memory
  649.  
  650.     call getfarfree
  651.     ; AX = size of largest free block
  652.  
  653.     This procedure returns the size of the largest free
  654.     block of far memory.  If there are no free blocks, 0
  655.     is returned.
  656.  
  657.  
  658.   ─────────────────────────────────────────────────────────────
  659.   ───────────────── Put/Get String Procedures ─────────────────
  660.   ─────────────────────────────────────────────────────────────
  661.  
  662.   ────────── puts               Put String
  663.  
  664.     push offset string
  665.     call puts
  666.  
  667.     This procedure writes a string to the screen.  If the
  668.     STDOUT handle is redirected, this still works.  The
  669.     string is output literally, using Int 29h.
  670.  
  671.   ────────── fputs              Put String to File
  672.  
  673.     push handle
  674.     push offset string
  675.     call fputs
  676.  
  677.     This procedure writes a string to a file.  If an error
  678.     occurs, -1 is returned, otherwise a nonzero value is
  679.     returned.  The handle is a FREELIB handle, not a DOS
  680.     handle.
  681.  
  682.   ────────── xputs              Put String, Generalized
  683.  
  684.     push offset outfunc
  685.     push offset string
  686.     call xputs
  687.  
  688.     This procedure outputs a string using a user-defined
  689.     function.  The function must take one word argument,
  690.     the character to output, save all registers, and return
  691.     with a 'Ret 2' to clean up the stack.
  692.  
  693.   ────────── gets               Get String
  694.  
  695.     push offset buffer
  696.     push max
  697.     call gets
  698.  
  699.     This procedure inputs a string from the keyboard.  The
  700.     string of maximum 'max' chars will be put into 'buffer'.
  701.     Any excess characters will be discarded.  This procedure
  702.     allows simple editing using the <BkSp> key.
  703.  
  704.   ────────── fgets              Get String from File
  705.  
  706.     push handle
  707.     push offset buffer
  708.     push max
  709.     call fgets
  710.     ; AX = return code
  711.  
  712.     This procedure reads a line from a file.  The string of
  713.     maximum 'max' chars will be read into 'buffer'.  The
  714.     line must end with a CR/LF pair.  An entire line will be
  715.     input even if it exceeds 'max' characters.  Any excess
  716.     will be discarded.  The handle is a FREELIB handle, not
  717.     a DOS handle.  If the end of file is reached, -1 is
  718.     returned, otherwise 0 is returned.
  719.  
  720.   ────────── xgets              Get String, Generalized
  721.  
  722.     push offset outfunc
  723.     push offset buffer
  724.     push max
  725.     push terminator
  726.     call xgets
  727.  
  728.     This procedure reads a logical line using a user-defined
  729.     function.  The function must take zero arguments and
  730.     return in AL the character input.  No register except
  731.     AX may be changed.  The value 'terminator' must be
  732.     returned on end of logical line.  The string of maximum
  733.     'max' chars will be read into 'buffer'.  An entire
  734.     logical line will be input even if it exceeds 'max'
  735.     characters.  Any excess will be discarded.
  736.  
  737.  
  738.   ─────────────────────────────────────────────────────────────
  739.   ───────────── Formatted String Print Procedures ─────────────
  740.   ─────────────────────────────────────────────────────────────
  741.  
  742.   ────────── printf             Print Formatted String
  743.  
  744.     push offset fmtstr
  745.     push offset arglist
  746.     call printf
  747.  
  748.     This procedure prints a formatted string to the screen.
  749.     It is similar to the 'printf()' in 'C'.  In the format
  750.     string, the '%' character is special.  The '%' character
  751.     can be followed by the following characters, which
  752.     indicate what type of argument to print:
  753.  
  754.       %d        Integer
  755.       %x        Hex integer
  756.       %s        String
  757.       %c        Character
  758.       %ld       Long integer
  759.       %lx       Long hex integer
  760.  
  761.     The parameter 'arglist' is a list of arguments, in
  762.     order.  Their types are taken from the format string.
  763.     If the wrong type is specified in the format string,
  764.     printf has no way of knowing, so the results will be
  765.     unpredictable.
  766.  
  767.     Example of using printf:
  768.  
  769. ;──────────────────────────────────────
  770.  
  771.             ...
  772.  
  773. FmtStr      db '%d %s %c %lx',0
  774.  
  775. ArgList     dw 15600
  776.             db 'This is a string',0
  777.             db 'X'
  778.             dd 1A2B3C4Dh
  779.  
  780.             ...
  781.  
  782.             push offset FmtStr
  783.             push offset ArgList
  784.             call printf
  785.  
  786.             ...
  787.  
  788. ;──────────────────────────────────────
  789.  
  790.     This example will output '15600 This is a string X 1A2B3C4D'.
  791.  
  792.   ────────── fprintf            Print Formatted String to File
  793.  
  794.     push handle
  795.     push offset fmtstr
  796.     push offset arglist
  797.     call printf
  798.  
  799.     This procedure prints a formatted string to a file.  It
  800.     works the same way printf does.  See 'printf' for more
  801.     information.
  802.  
  803.   ────────── sprintf            Print Formatted String to String
  804.  
  805.     push offset dest_str
  806.     push offset fmtstr
  807.     push offset arglist
  808.     call printf
  809.  
  810.     This procedure prints a formatted string to a string.
  811.     The string output will be null terminated.  This
  812.     procedure works the same way printf does.  See 'printf'
  813.     for more information.
  814.  
  815.   ────────── xprintf            Print Formatted String, Generalized
  816.  
  817.     push offset outfunc
  818.     push offset fmtstr
  819.     push offset arglist
  820.     call printf
  821.  
  822.     This procedure prints a formatted string using a user
  823.     defined function.  The function must take one word
  824.     argument, the character to output, save all registers,
  825.     and return with a 'Ret 2' to clean up the stack.  This
  826.     procedure works the same way printf does.  See 'printf'
  827.     for more information.
  828.  
  829.  
  830.   ─────────────────────────────────────────────────────────────
  831.   ──────────── Alphanumeric Conversion Procedures ─────────────
  832.   ─────────────────────────────────────────────────────────────
  833.  
  834.   ────────── atoi               Convert String to Integer
  835.  
  836.     push offset string
  837.     call atoi
  838.     ; AX = result
  839.  
  840.     This procedure converts a string to an integer.  It
  841.     recognizes the '-' and '+' signs, but it will stop on
  842.     any other non-digit.  The integer corresponding to the
  843.     string is returned.  If the result overflows, the low
  844.     16 bits of the result are returned.
  845.  
  846.   ────────── atol               Convert String to Long
  847.  
  848.     push offset string
  849.     call atol
  850.     ; DX:AX = result
  851.  
  852.     This procedure converts a string to a long integer.
  853.     It recognizes the '-' and '+' signs, but it will stop on
  854.     any other non-digit.  The long integer corresponding to
  855.     the string is returned.  If the result overflows, the
  856.     low 32 bits of the result are returned.
  857.  
  858.   ────────── itoa               Convert Integer to String
  859.  
  860.     push number
  861.     push offset buffer
  862.     call itoa
  863.  
  864.     This procedure converts an integer to a string.  On
  865.     return, 'buffer' will contain the decimal representation
  866.     of 'number'.  The string will be null terminated.  If
  867.     the number is negative, this will be handled correctly.
  868.  
  869.   ────────── ltoa               Convert Long to String
  870.  
  871.     push num_hi
  872.     push num_lo
  873.     push offset buffer
  874.     call ltoa
  875.  
  876.     This procedure converts a long integer to a string.  On
  877.     return, 'buffer' will contain the decimal representation
  878.     of the number.  The string will be null terminated.  If
  879.     the number is negative, this will be handled correctly.
  880.  
  881.   ────────── atofix             Convert String to Fixed-Point
  882.  
  883.     push offset string
  884.     call atofix
  885.     ; DX:AX = result
  886.  
  887.     This procedure converts a string to a fixed-point
  888.     number.  Itrecognizes the '-' and '+' signs and the
  889.     decimal point, but it will stop on any other non-digit.
  890.     The fixed-point number corresponding to the string is
  891.     returned.  If the result overflows, the value returned
  892.     will have the correct fractional part, and the integer
  893.     part will be the low 16 bits of the true value.
  894.  
  895.   ────────── fixtoa             Convert Fixed-Point to String
  896.  
  897.     push num_hi
  898.     push num_lo
  899.     push offset buffer
  900.     call fixtoa
  901.  
  902.     This procedure converts a fixed-point number to a
  903.     string.  On return, 'buffer' will contain the decimal
  904.     representation of the number.  The string will be null
  905.     terminated.  If the number is negative, this will be
  906.     handled correctly.  Fractions will also be handled
  907.     correctly.
  908.  
  909.   ────────── roman              Convert Integer to Roman Numerals
  910.  
  911.     push number
  912.     push offset buffer
  913.     call roman
  914.  
  915.     This procedure converts an integer to Roman Numerals.
  916.     On return, 'buffer' will contain the Roman Numeral
  917.     representation of 'number'.  The string will be null
  918.     terminated.  If the number is negative or zero, a null
  919.     string will be output.
  920.  
  921.  
  922.   ─────────────────────────────────────────────────────────────
  923.   ────── Long Integer/Fixed Point Arithmetic Procedures ───────
  924.   ─────────────────────────────────────────────────────────────
  925.  
  926.   ────────── ldiv               Long Divide
  927.  
  928.     push num1_hi
  929.     push num1_lo
  930.     push num2_hi
  931.     push num2_lo
  932.     call ldiv
  933.     ; DX:AX = result
  934.  
  935.     This procedure divides unsigned long integers.
  936.     It divides 'num1' by 'num2'.
  937.  
  938.   ────────── lidiv              Long Divide, Signed
  939.  
  940.     push num1_hi
  941.     push num1_lo
  942.     push num2_hi
  943.     push num2_lo
  944.     call lidiv
  945.     ; DX:AX = result
  946.  
  947.     This procedure divides signed long integers.
  948.     It divides 'num1' by 'num2'.
  949.  
  950.   ────────── lmul               Long Multiply
  951.  
  952.     push num1_hi
  953.     push num1_lo
  954.     push num2_hi
  955.     push num2_lo
  956.     call lmul
  957.     ; DX:AX = result
  958.  
  959.     This procedure multiplies unsigned long integers.
  960.     It takes 70 clock ticks on a 486, including the
  961.     call/return but not the argument pushes.
  962.  
  963.   ────────── limul              Long Multiply, Signed
  964.  
  965.     push num1_hi
  966.     push num1_lo
  967.     push num2_hi
  968.     push num2_lo
  969.     call limul
  970.     ; DX:AX = result
  971.  
  972.     This procedure multiplies signed long integers.
  973.     It takes 89-97 clock ticks on a 486, including the
  974.     call/return but not the argument pushes.
  975.  
  976.   ────────── lmod               Long Modulo
  977.  
  978.     push num1_hi
  979.     push num1_lo
  980.     push num2_hi
  981.     push num2_lo
  982.     call lmod
  983.     ; DX:AX = result
  984.  
  985.     This procedure does the modulo operation on unsigned
  986.     long integers.   It divides 'num1' by 'num2' and returns
  987.     the remainder.
  988.  
  989.   ────────── limod              Long Modulo, Signed
  990.  
  991.     push num1_hi
  992.     push num1_lo
  993.     push num2_hi
  994.     push num2_lo
  995.     call limod
  996.     ; DX:AX = result
  997.  
  998.     This procedure does the modulo operation on signed long
  999.     integers.   It divides 'num1' by 'num2' and returns the
  1000.     remainder.
  1001.  
  1002.   ────────── lshl               Long Shift Left
  1003.  
  1004.     push num_hi
  1005.     push num_lo
  1006.     push dist
  1007.     call lshl
  1008.     ; DX:AX = result
  1009.  
  1010.     This procedure shifts a long integer to the left.
  1011.     It shifts 'num' by 'dist', and takes 37 clock
  1012.     ticks on a 486, including the call/return but not
  1013.     the argument pushes.
  1014.  
  1015.   ────────── lshr               Long Shift Right
  1016.  
  1017.     push num_hi
  1018.     push num_lo
  1019.     push dist
  1020.     call lshr
  1021.     ; DX:AX = result
  1022.  
  1023.     This procedure shifts an unsigned long integer to the
  1024.     right.  It shifts 'num' by 'dist', and takes 37 clock
  1025.     ticks on a 486, including the call/return but not
  1026.     the argument pushes.
  1027.  
  1028.   ────────── lsar               Long Shift Right, Signed
  1029.  
  1030.     push num_hi
  1031.     push num_lo
  1032.     push dist
  1033.     call lsar
  1034.     ; DX:AX = result
  1035.  
  1036.     This procedure shifts a signed long integer to the
  1037.     right.  It shifts 'num' by 'dist', and takes 39 clock
  1038.     ticks on a 486, including the call/return but not
  1039.     the argument pushes.
  1040.  
  1041.   ────────── fixmul             Fixed-Point Multiply
  1042.  
  1043.     push num1_hi
  1044.     push num1_lo
  1045.     push num2_hi
  1046.     push num2_lo
  1047.     call fixmul
  1048.     ; DX:AX = result
  1049.  
  1050.     This procedure multiplies fixed-point numbers.
  1051.     It takes 101-109 clock ticks on a 486, including
  1052.     the call/return but not the argument pushes.
  1053.  
  1054.   ────────── fixdiv             Fixed-Point Divide
  1055.  
  1056.     push num1_hi
  1057.     push num1_lo
  1058.     push num2_hi
  1059.     push num2_lo
  1060.     call fixdiv
  1061.     ; DX:AX = result
  1062.  
  1063.     This procedure divides fixed-point numbers.
  1064.     It divides 'num1' by 'num2'.
  1065.  
  1066.  
  1067.   ─────────────────────────────────────────────────────────────
  1068.   ───────────────── Trigonometric Procedures ──────────────────
  1069.   ─────────────────────────────────────────────────────────────
  1070.  
  1071.   ────────── sine               Sine
  1072.  
  1073.     push num_hi
  1074.     push num_lo
  1075.     call sine
  1076.     ; DX:AX = result
  1077.  
  1078.     This procedure calculates the trigonometric sine of
  1079.     'num'.  It operates on fixed-point numbers.  The input
  1080.     value should be in radians.
  1081.  
  1082.   ────────── cosine             Cosine
  1083.  
  1084.     push num_hi
  1085.     push num_lo
  1086.     call cosine
  1087.     ; DX:AX = result
  1088.  
  1089.     This procedure calculates the trigonometric cosine of
  1090.     'num'.  It operates on fixed-point numbers.  The input
  1091.     value should be in radians.
  1092.  
  1093.   ────────── tangent            Tangent
  1094.  
  1095.     push num_hi
  1096.     push num_lo
  1097.     call tangent
  1098.     ; DX:AX = result
  1099.  
  1100.     This procedure calculates the trigonometric tangent of
  1101.     'num'.  It operates on fixed-point numbers.  The input
  1102.     value should be in radians.
  1103.  
  1104.   ────────── cotangent          Cotangent
  1105.  
  1106.     push num_hi
  1107.     push num_lo
  1108.     call cotangent
  1109.     ; DX:AX = result
  1110.  
  1111.     This procedure calculates the trigonometric cotangent of
  1112.     'num'.  It operates on fixed-point numbers.  The input
  1113.     value should be in radians.
  1114.  
  1115.   ────────── secant             Secant
  1116.  
  1117.     push num_hi
  1118.     push num_lo
  1119.     call secant
  1120.     ; DX:AX = result
  1121.  
  1122.     This procedure calculates the trigonometric secant of
  1123.     'num'.  It operates on fixed-point numbers.  The input
  1124.     value should be in radians.
  1125.  
  1126.   ────────── cosecant           Cosecant
  1127.  
  1128.     push num_hi
  1129.     push num_lo
  1130.     call cosecant
  1131.     ; DX:AX = result
  1132.  
  1133.     This procedure calculates the trigonometric cosecant of
  1134.     'num'.  It operates on fixed-point numbers.  The input
  1135.     value should be in radians.
  1136.  
  1137.  
  1138.   ─────────────────────────────────────────────────────────────
  1139.   ───────────────────── String Procedures ─────────────────────
  1140.   ─────────────────────────────────────────────────────────────
  1141.  
  1142.   ────────── strlen             String Length
  1143.  
  1144.     push offset string
  1145.     call strlen
  1146.     ; AX = length
  1147.  
  1148.     This procedure returns the length of a string, not
  1149.     including the null terminator.
  1150.  
  1151.   ────────── strcpy             Copy String
  1152.  
  1153.     push offset dest_str
  1154.     push offset src_str
  1155.     call strcpy
  1156.  
  1157.     This procedure copies 'src_str' to 'dest_str', including
  1158.     the null terminator.  There is no checking to see if the
  1159.     string fits, so be careful.
  1160.  
  1161.   ────────── strcat             Concatenate Strings
  1162.  
  1163.     push offset dest_str
  1164.     push offset src_str
  1165.     call strcat
  1166.  
  1167.     This procedure concatenates 'src_str' onto 'dest_str',
  1168.     including the null terminator.  There is no checking to
  1169.     see if the string fits, so be careful.
  1170.  
  1171.   ────────── strcmp             Compare Strings
  1172.  
  1173.     push offset string1
  1174.     push offset string2
  1175.     call strcmp
  1176.     ; AX  = return value
  1177.  
  1178.     This procedure compares 'string1' and 'string2'.  If
  1179.     'string2' is lexicographically greater, a negative value
  1180.     is returned.  If 'string1' is greater, a positive value
  1181.     is returned.  If they are equal, zero is returned.
  1182.  
  1183.   ────────── stricmp            Compare Strings, Case Insensitive
  1184.  
  1185.     push offset string1
  1186.     push offset string2
  1187.     call stricmp
  1188.     ; AX  = return value
  1189.  
  1190.     This procedure compares 'string1' and 'string2'.  If
  1191.     'string2' is lexicographically greater, a negative value
  1192.     is returned.  If 'string1' is greater, a positive value
  1193.     is returned.  If they are equal, zero is returned.  This
  1194.     procedure differs from strcmp in that the compare is
  1195.     case insensitive.
  1196.  
  1197.   ────────── strchr             Search String for Char
  1198.  
  1199.     push offset string
  1200.     push char
  1201.     call strchr
  1202.     ; AX  = return value
  1203.  
  1204.     This procedure searches for 'char' in 'string'.  If the
  1205.     character is not found, -1 is returned, otherwise the
  1206.     position of the character in the string is returned.
  1207.  
  1208.   ────────── strstr             Search String for Substring
  1209.  
  1210.     push offset string
  1211.     push offset substr
  1212.     call strchr
  1213.     ; AX  = return value
  1214.  
  1215.     This procedure searches for 'substr' in 'string'.  If
  1216.     the substring is not found, -1 is returned, otherwise
  1217.     the position of the substring in the main string is
  1218.     returned.
  1219.  
  1220.   ────────── strlwr             Convert String to Lowercase
  1221.  
  1222.     push offset string
  1223.     call strlwr
  1224.  
  1225.     This procedure converts a string to lowercase.  Any
  1226.     character in the string that is already lowercase or
  1227.     that is not a letter will not be affected.
  1228.  
  1229.   ────────── strupr             Convert String to Uppercase
  1230.  
  1231.     push offset string
  1232.     call strupr
  1233.  
  1234.     This procedure converts a string to uppercase.  Any
  1235.     character in the string that is already uppercase or
  1236.     that is not a letter will not be affected.
  1237.  
  1238.   ────────── strltrim           Trim Leading Spaces
  1239.  
  1240.     push offset string
  1241.     call strltrim
  1242.  
  1243.     This procedure trims leading spaces from a string.  If
  1244.     there are no leading spaces, nothing happens.
  1245.  
  1246.   ────────── strrtrim           Trim Trailing Spaces
  1247.  
  1248.     push offset string
  1249.     call strrtrim
  1250.  
  1251.     This procedure trims trailing spaces from a string.  If
  1252.     there are no trailing spaces, nothing happens.
  1253.  
  1254.  
  1255.   ─────────────────────────────────────────────────────────────
  1256.   ────────────────── Memory Block Procedures ──────────────────
  1257.   ─────────────────────────────────────────────────────────────
  1258.  
  1259.   ────────── memcpy             Copy Memory Block
  1260.  
  1261.     push dest_offset
  1262.     push src_offset
  1263.     push length
  1264.     call memcpy
  1265.  
  1266.     This procedure copies a block of memory from
  1267.     'src_offset' to 'dest_offset'.  The block is of length
  1268.     'length'.  This procedure will work correctly if the
  1269.     blocks overlap.
  1270.  
  1271.   ────────── memset             Set Memory Block
  1272.  
  1273.     push mem_offset
  1274.     push length
  1275.     push byte
  1276.     call memset
  1277.  
  1278.     This procedure fills a block of memory of length
  1279.     'length' at 'mem_offset' with 'byte'.
  1280.  
  1281.   ────────── memcmp             Compare Memory Blocks
  1282.  
  1283.     push dest_offset
  1284.     push src_offset
  1285.     push length
  1286.     call memcmp
  1287.     ; AX = return code
  1288.  
  1289.     This procedure compares two blocks of memory at offsets
  1290.     'src_offset' and 'dest_offset'.  The blocks are of
  1291.     length 'length'.  If they are equal, 1 is returned,
  1292.     otherwise 0 is returned.
  1293.  
  1294.   ────────── memchr             Search Memory Block
  1295.  
  1296.     push mem_offset
  1297.     push length
  1298.     push byte
  1299.     call memchr
  1300.  
  1301.     This procedure searches a block of memory of length
  1302.     'length' at 'src_offset' for 'byte'.  If the byte is
  1303.     found, its position within the block is returned,
  1304.     otherwise -1 is returned.
  1305.  
  1306.  
  1307.   ─────────────────────────────────────────────────────────────
  1308.   ──────────────── Search and Sort Procedures ─────────────────
  1309.   ─────────────────────────────────────────────────────────────
  1310.  
  1311.   ────────── isearch            Search Array of Integers
  1312.  
  1313.     push offset array
  1314.     push size
  1315.     push elem
  1316.     call isearch
  1317.     ; AX = return code
  1318.  
  1319.     This procedure searches an array of integers of size
  1320.     'size' for 'elem'.  This procedure assumes that the
  1321.     array is sorted.  If the element is found, its position
  1322.     in the array is returned, otherwise -1 is returned.
  1323.  
  1324.   ────────── lsearch            Search Array of Longs
  1325.  
  1326.     push offset array
  1327.     push size
  1328.     push elem_hi
  1329.     push elem_lo
  1330.     call lsearch
  1331.     ; AX = return code
  1332.  
  1333.     This procedure searches an array of long integers of
  1334.     size 'size' for 'elem'.  This procedure assumes that the
  1335.     array is sorted.  If the element is found, its position
  1336.     in the array is returned, otherwise -1 is returned.
  1337.  
  1338.   ────────── ssearch            Search Array of Strings
  1339.  
  1340.     push offset array
  1341.     push size
  1342.     push offset elem
  1343.     call ssearch
  1344.     ; AX = return code
  1345.  
  1346.     This procedure searches an array of strings of size
  1347.     'size' for 'elem'.  This procedure assumes that the
  1348.     array is sorted.  If the element is found, its position
  1349.     in the array is returned, otherwise -1 is returned.
  1350.  
  1351.   ────────── xsearch            Search Array, Generalized
  1352.  
  1353.     push offset array
  1354.     push size
  1355.     push offset elem
  1356.     push offset cmpfunc
  1357.     call xsearch
  1358.     ; AX = return code
  1359.  
  1360.     This procedure searches an array of pointers of size
  1361.     'size' for 'elem'.  It assumes that the array is sorted.
  1362.     If the element is found, its position in the array is
  1363.     returned, otherwise -1 is returned.
  1364.  
  1365.     This procedure uses a user-defined function.  The
  1366.     function must take two word-sized pointer arguments.
  1367.     It must return the result of the comparison in AX so
  1368.     that a negative value indicates less, a positive value
  1369.     indicates greater, and zero indicates equal, and it
  1370.     also should preserve all registers except for AX.
  1371.  
  1372.   ────────── isort              Sort Array of Integers
  1373.  
  1374.     push offset array
  1375.     push size
  1376.     call isort
  1377.  
  1378.     This procedure sorts an array of integers of size
  1379.     'size' in ascending order.
  1380.  
  1381.   ────────── lsort              Sort Array of Longs
  1382.  
  1383.     push offset array
  1384.     push size
  1385.     call lsort
  1386.  
  1387.     This procedure sorts an array of long integers of size
  1388.     'size' in ascending order.
  1389.  
  1390.   ────────── ssort              Sort Array of Strings
  1391.  
  1392.     push offset array
  1393.     push size
  1394.     call ssort
  1395.  
  1396.     This procedure sorts an array of strings of size
  1397.     'size' in alphabetical order.
  1398.  
  1399.   ────────── xsort              Sort Array, Generalized
  1400.  
  1401.     push offset array
  1402.     push size
  1403.     push offset cmpfunc
  1404.     call xsort
  1405.  
  1406.     This procedure sorts an array of pointers of size
  1407.     'size'.  This is the generalized sort procedure.
  1408.  
  1409.     This procedure uses a user-defined function.  The
  1410.     function must take two word-sized pointer arguments.
  1411.     It must return the result of the comparison in AX so
  1412.     that a negative value indicates less, a positive value
  1413.     indicates greater, and zero indicates equal, and it
  1414.     also should preserve all registers except for AX.
  1415.  
  1416.  
  1417.   ─────────────────────────────────────────────────────────────
  1418.   ───────────────── Miscellaneous Procedures ──────────────────
  1419.   ─────────────────────────────────────────────────────────────
  1420.  
  1421.   ────────── cputype            Get CPU Type
  1422.  
  1423.     call cputype
  1424.     ; AX = CPU type
  1425.  
  1426.     This procedure returns the CPU type (0 = 8086, 1 = 186,
  1427.     etc.)  It cannot detect SX/DX variations.
  1428.  
  1429.   ────────── fputype            Get FPU Type
  1430.  
  1431.     call fputype
  1432.     ; AX = FPU type
  1433.  
  1434.     This procedure returns the FPU type (0 = 8087, 1 = 187,
  1435.     etc.)  If there is no FPU, -1 is returned.
  1436.  
  1437.   ────────── crc16              16-Bit CRC
  1438.  
  1439.     push offset buf
  1440.     push count
  1441.     call crc16
  1442.     ; AX = CRC16 value
  1443.  
  1444.     This procedure returns the CRC16 checksum of the block
  1445.     of memory at 'buf' of length 'count'.
  1446.  
  1447.   ────────── crc32              32-Bit CRC
  1448.  
  1449.     push offset buf
  1450.     push count
  1451.     call crc32
  1452.     ; DX:AX = CRC32 value
  1453.  
  1454.     This procedure returns the CRC32 checksum of the block
  1455.     of memory at 'buf' of length 'count'.
  1456.  
  1457.   ────────── atexit             Register Exit Function
  1458.  
  1459.     push offset func
  1460.     call atexit
  1461.  
  1462.     This procedure registers a function for calling on exit.
  1463.     If an error occurs, 0 is returned, otherwise a nonzero
  1464.     value is returned.
  1465.  
  1466.   ────────── bitcnt             Count Bits
  1467.  
  1468.     push number
  1469.     call bitcnt
  1470.     ; AX = number of set bits
  1471.  
  1472.     This procedure returns the number of set bits in an
  1473.     integer.
  1474.  
  1475.   ────────── highbit            Find High Bit
  1476.  
  1477.     push number
  1478.     call highbit
  1479.     ; AX = highest bit
  1480.  
  1481.     This procedure returns the positon of the highest set
  1482.     bit in an integer.  -1 is returned if it is zero.
  1483.  
  1484.   ────────── sqrt               Square Root
  1485.  
  1486.     push num_hi
  1487.     push num_lo
  1488.     call sqrt
  1489.     ; AX = result
  1490.  
  1491.     This procedure returns the square root of a long
  1492.     integer.  The result is a normal integer.  This
  1493.     procedure treats all values as unsigned.
  1494.  
  1495.   ────────── exec               Execute Program
  1496.  
  1497.     push offset progname
  1498.     push offset cmdline
  1499.     call exec
  1500.     ; AX = return code
  1501.  
  1502.     This procedure executes another program as a child
  1503.     process, with arguments in 'cmdline'.  If an error
  1504.     occurs, 0 is returned, otherwise a nonzero value
  1505.     is returned.
  1506.  
  1507.   ────────── rand               Random Number
  1508.  
  1509.     push max
  1510.     call rand
  1511.     ; AX = result
  1512.  
  1513.     This procedure returns a random number below 'max'.
  1514.  
  1515.   ────────── srand              Seed Random Numbers
  1516.  
  1517.     call srand
  1518.  
  1519.     This procedure seeds the random number generator with
  1520.     the system clock.
  1521.  
  1522.   ────────── truerand           True Random Number
  1523.  
  1524.     push max
  1525.     call truerand
  1526.     ; AX = result
  1527.  
  1528.     This procedure returns a true random number below 'max'.
  1529.  
  1530.     This is not a pseudo-random RNG.  This procedure reads
  1531.     random bits of the system timer to generate the numbers,
  1532.     so the number is truly random.  This procedure has been
  1533.     tested for randomness by exhaustively analyzing 140 MB
  1534.     of random data.
  1535.  
  1536.     However, this routine is extremely slow.  It generates
  1537.     only about 760 random numbers per second on a 486DX2/66.
  1538.  
  1539.  
  1540.   ────────── delay              Delay
  1541.  
  1542.     push delaytime
  1543.     call delay
  1544.  
  1545.     This procedure delays for a specified number of
  1546.     milliseconds before returning.
  1547.  
  1548.   ────────── sound              Set Speaker
  1549.  
  1550.     push freq
  1551.     call sound
  1552.  
  1553.     This procedure turns on the speaker at a specified
  1554.     frequency.
  1555.  
  1556.   ────────── nosound            Turn Speaker Off
  1557.  
  1558.   call nosound
  1559.  
  1560.   This procedure turns the speaker off.
  1561.  
  1562.  
  1563.   ─────────────────────────────────────────────────────────────
  1564.   ─────────── High-Res Text Mode (90x34) Procedures ───────────
  1565.   ─────────────────────────────────────────────────────────────
  1566.  
  1567.   ────────── inittext           Initialize Text System
  1568.  
  1569.     call inittext
  1570.  
  1571.     This procedure initializes the High-Res Text Mode.
  1572.  
  1573.   ────────── closetext          Close Text System
  1574.  
  1575.     call closetext
  1576.  
  1577.     This procedure closes the High-Res Text system, and
  1578.     sets the standard text mode.
  1579.  
  1580.   ────────── clrscr             Clear Screen
  1581.  
  1582.     call clrscr
  1583.  
  1584.     This procedure clears the screen on the current video
  1585.     page.
  1586.  
  1587.   ────────── setwin             Set Window
  1588.  
  1589.     push x1 y1
  1590.     push x2 y2
  1591.     push rel_flag
  1592.     call setwin
  1593.  
  1594.     This procedure sets the clipping window.  'rel_flag'
  1595.     indicates whether coordinates will be relative to the
  1596.     window or not.
  1597.  
  1598.   ────────── clrwin             Clear Window
  1599.  
  1600.     call clrwin
  1601.  
  1602.     This procedure clears the current window.
  1603.  
  1604.   ────────── setpage            Set Video Page
  1605.  
  1606.     push page_num
  1607.     call setpage
  1608.  
  1609.     This procedure sets the current video page.  The page
  1610.     number must be between 0 and 5 (there are six pages).
  1611.  
  1612.   ────────── getpage            Get Video Page
  1613.  
  1614.     call getpage
  1615.     ; AX = current page
  1616.  
  1617.     This procedure returns the current video page.
  1618.  
  1619.   ────────── setcolor           Set Color
  1620.  
  1621.     push color
  1622.     call setcolor
  1623.  
  1624.     This procedure sets the current text color.  The color
  1625.     is a byte, 0XYh, where X is the background color and Y
  1626.     is the foreground color.
  1627.  
  1628.   ────────── getcolor           Get Color
  1629.  
  1630.     call getcolor
  1631.     ; AX = current color
  1632.  
  1633.     This procedure returns the current text color.
  1634.  
  1635.   ────────── box                Draw Box
  1636.  
  1637.     push x1 y1
  1638.     push x2 y2
  1639.     push char
  1640.     call box
  1641.  
  1642.     This procedure draws a box with character 'char'.  The
  1643.     box is clipped to the current window.
  1644.  
  1645.   ────────── sbox               Draw Style Box
  1646.  
  1647.     push x1 y1
  1648.     push x2 y2
  1649.     push style
  1650.     call sbox
  1651.  
  1652.     This procedure draws a style box.  The box is clipped
  1653.     to the current window.  Here is the list of styles:
  1654.  
  1655.     0       Blank
  1656.     1       Single Line
  1657.     2       Double Line
  1658.     3       Single/Double
  1659.     4       Double/Single
  1660.  
  1661.   ────────── fbox               Draw Filled Box
  1662.  
  1663.     push x1 y1
  1664.     push x2 y2
  1665.     push char
  1666.     call fbox
  1667.  
  1668.     This procedure draws a filled box with character 'char'.
  1669.     The box is clipped to the current window.
  1670.  
  1671.   ────────── hline              Draw Horizontal Line
  1672.  
  1673.     push x1 x2
  1674.     push y
  1675.     push char
  1676.     call hline
  1677.  
  1678.     This procedure draws a horizontal line with character
  1679.     'char'.  The line is clipped to the current window.
  1680.  
  1681.   ────────── vline              Draw Vertical Line
  1682.  
  1683.     push y1 y2
  1684.     push x
  1685.     push char
  1686.     call vline
  1687.  
  1688.     This procedure draws a vertical line with character
  1689.     'char'.  The line is clipped to the current window.
  1690.  
  1691.   ────────── hsline             Draw Horizontal Style Line
  1692.  
  1693.     push x1 x2
  1694.     push y
  1695.     push style
  1696.     call hsline
  1697.  
  1698.     This procedure draws a horizontal style line.  The line
  1699.     is clipped to the current window.  See the description
  1700.     for 'sbox' for a list of the styles.
  1701.  
  1702.   ────────── vsline             Draw Vertical Style Line
  1703.  
  1704.     push y1 y2
  1705.     push x
  1706.     push style
  1707.     call vsline
  1708.  
  1709.     This procedure draws a horizontal style line.  The line
  1710.     is clipped to the current window.  See the description
  1711.     for 'sbox' for a list of the styles.
  1712.  
  1713.   ────────── gotoxy             Set Cursor Position
  1714.  
  1715.     push x y
  1716.     call gotoxy
  1717.  
  1718.     This procedure sets the position of the cursor.  It is
  1719.     clipped to the current window.
  1720.  
  1721.   ────────── getx               Get Cursor X
  1722.  
  1723.     call getx
  1724.     ; AX = current X position
  1725.  
  1726.     This procedure returns the X position of the cursor.  If
  1727.     the window relative flag is set, the position will be
  1728.     relative to the current window.
  1729.  
  1730.   ────────── gety               Get Cursor Y
  1731.  
  1732.     call gety
  1733.     ; AX = current Y position
  1734.  
  1735.     This procedure returns the Y position of the cursor.  If
  1736.     the window relative flag is set, the position will be
  1737.     relative to the current window.
  1738.  
  1739.   ────────── setctype           Set Cursor Type
  1740.  
  1741.     push cur_type
  1742.     call setctype
  1743.  
  1744.     This procedure sets the type of the cursor.  The format
  1745.     is: 0XXYYh, where XX is the starting line (0-13) and YY
  1746.     is the ending line (0-13).
  1747.  
  1748.   ────────── getctype           Get Cursor Type
  1749.  
  1750.     call getctype
  1751.     ; AX = cursor type
  1752.  
  1753.     This procedure returns the current cursor type.  The
  1754.     format is: 0XXYYh, where XX is the starting line (0-13)
  1755.     and YY is the ending line (0-13).
  1756.  
  1757.   ────────── setch              Set Character
  1758.  
  1759.     push x y
  1760.     push char
  1761.     call setch
  1762.  
  1763.     This procedure sets the character at (x, y) to 'char'.
  1764.     The output is clipped to the current window.
  1765.  
  1766.   ────────── setat              Set Attribute
  1767.  
  1768.     push x y
  1769.     push attr
  1770.     call setat
  1771.  
  1772.     This procedure sets the attribute at (x, y) to 'attr'.
  1773.     The output is clipped to the current window.
  1774.  
  1775.   ────────── setcha             Set Char & Attr.
  1776.  
  1777.     push x y
  1778.     push char
  1779.     push attr
  1780.     call setcha
  1781.  
  1782.     This procedure sets the character at (x, y) to 'char',
  1783.     and the attribute to 'attr'.  The output is clipped to
  1784.     the current window.
  1785.  
  1786.   ────────── readcha            Read Char & Attr.
  1787.  
  1788.     push x y
  1789.     call readcha
  1790.     ; AL = char, AH = attr
  1791.  
  1792.     This procedure returns the character and attribute
  1793.     at (x, y).
  1794.  
  1795.   ────────── tputs              Put String at (X, Y)
  1796.  
  1797.     push x y
  1798.     push offset string
  1799.     call tputs
  1800.  
  1801.     This procedure prints 'string' at (x, y).  Output is
  1802.     clipped to the current window.  Output will not wrap
  1803.     around lines.  Control characters will be displayed
  1804.     literally.
  1805.  
  1806.   ────────── tprintf            Print Formatted String at (X, Y)
  1807.  
  1808.     push x y
  1809.     push offset fmtstr
  1810.     push offset arglist
  1811.     call tprintf
  1812.  
  1813.     This procedure prints a formatted string at (x, y).
  1814.     It is equivalent to a 'sprintf' followed by 'tputs'.
  1815.     See 'sprintf' and 'tputs' for more information.
  1816.  
  1817.   ────────── getline            Get Line of Text
  1818.  
  1819.     push x y
  1820.     push offset buffer
  1821.     push min
  1822.     push max
  1823.     call getline
  1824.  
  1825.     This procedure inputs a line of text from the user.
  1826.     A field is drawn at (x, y) extending for (max - 1)
  1827.     characters, and the string is input there.  Full
  1828.     editing, i.e. insert/delete, etc., is supported.
  1829.     A string of minimum 'min' and maximum (max - 1)
  1830.     characters will be put into 'buffer'.
  1831.  
  1832.   ────────── setglchar          Set Char for 'getline'
  1833.  
  1834.     push char
  1835.     call setglchar
  1836.  
  1837.     This sets the character used to clear the input field in
  1838.     'getline'.  The default value is a space (20h).  Another
  1839.     useful value is the small bullet (0FAh).
  1840.  
  1841.   ────────── gettext            Get Block of Text
  1842.  
  1843.     push offset buffer
  1844.     push x1 y1
  1845.     push x2 y2
  1846.     call gettext
  1847.  
  1848.     This procedure captures a rectangular block of text into
  1849.     'buffer'.  No clipping is performed.
  1850.  
  1851.   ────────── puttext            Put Block of Text
  1852.  
  1853.     push offset buffer
  1854.     push x1 y1
  1855.     call puttext
  1856.  
  1857.     This procedure displays a rectangular block of text from
  1858.     'buffer' at (x1, y1).  Output is clipped to the current
  1859.     window.
  1860.  
  1861.   ────────── movetext           Move Block of Text
  1862.  
  1863.     push x1 y1
  1864.     push x2 y2
  1865.     push x y
  1866.     call movetext
  1867.  
  1868.     This procedure moves a rectangular block of text from
  1869.     (x1, y1)-(x2, y2) to (x, y).  If the blocks overlap,
  1870.     it will be handled correctly.  No clipping is performed
  1871.     and the window relative flag is ignored.
  1872.  
  1873.   ────────── delline            Delete Line
  1874.  
  1875.     push y
  1876.     call delline
  1877.  
  1878.     This procedure deletes a line (at 'y') from the current
  1879.     window.  All text below the line is scrolled up, and the
  1880.     bottom line is cleared.
  1881.  
  1882.   ────────── insline            Insert Line
  1883.  
  1884.     push y
  1885.     call insline
  1886.  
  1887.     This procedure inserts a line (at 'y') from the current
  1888.     window.  All text below the line is scrolled down, and
  1889.     the inserted line is cleared.
  1890.  
  1891.   ────────── scroll             Scroll Window
  1892.  
  1893.     push dir
  1894.     call scroll
  1895.  
  1896.     This procedure scrolls the current window.  The values
  1897.     for the direction 'dir' are:
  1898.  
  1899.     0       Scroll Up
  1900.     1       Scroll Down
  1901.     2       Scroll Left
  1902.     3       Scroll Right
  1903.  
  1904.  
  1905.   ─────────────────────────────────────────────────────────────
  1906.   ──────── High-Res Text Mode (90x34) Mouse Procedures ────────
  1907.   ─────────────────────────────────────────────────────────────
  1908.  
  1909.   ────────── minit              Initialize Mouse System
  1910.  
  1911.     call minit
  1912.     ; AX = return code
  1913.  
  1914.     This procedure initializes the High-Res Text Mode
  1915.     Mouse Driver.  If an error occurs or the mouse is
  1916.     not found, 0 is returned, otherwise a nonzero value
  1917.     is returned.
  1918.  
  1919.   ────────── mclose             Close Mouse System
  1920.  
  1921.     call mclose
  1922.  
  1923.     This procedure closes the mouse system.
  1924.  
  1925.   ────────── mshow              Show Mouse Cursor
  1926.  
  1927.     call mshow
  1928.  
  1929.     This procedure displays the mouse cursor on the screen.
  1930.  
  1931.   ────────── mhide              Hide Mouse Cursor
  1932.  
  1933.     call mhide
  1934.  
  1935.     This procedure hides the mouse cursor.
  1936.  
  1937.   ────────── mget               Get Mouse Position
  1938.  
  1939.     call mget
  1940.     ; AX = button status
  1941.     ; BX = mouse X position
  1942.     ; CX = mouse Y position
  1943.  
  1944.     This procedure returns the position and status of the
  1945.     mouse.  The format for the button status is:
  1946.  
  1947.     Bit     Meaning
  1948.  
  1949.      0     Left button
  1950.      1     Right button
  1951.      2     Middle button
  1952.  
  1953.   ────────── mgetdn             Get Mouse Presses
  1954.  
  1955.     push button
  1956.     call mgetdn
  1957.     ; AX = press count
  1958.     ; BX = X position at last press
  1959.     ; CX = Y position at last press
  1960.  
  1961.     This procedure returns the status of a particular mouse
  1962.     button, for presses.  The button values are as follows:
  1963.  
  1964.     0       Left button
  1965.     1       Right button
  1966.     2       Middle button
  1967.  
  1968.   ────────── mgetup             Get Mouse Releases
  1969.  
  1970.     push button
  1971.     call mgetup
  1972.     ; AX = release count
  1973.     ; BX = X position at last release
  1974.     ; CX = Y position at last release
  1975.  
  1976.     This procedure returns the status of a particular mouse
  1977.     button, for releases.  See 'mgetup' for button values.
  1978.  
  1979.  
  1980.   ─────────────────────────────────────────────────────────────
  1981.   ──────────── Integrated VGA Graphics Procedures ─────────────
  1982.   ─────────────────────────────────────────────────────────────
  1983.  
  1984.   ────────── initgraph          Initialize Graphics System
  1985.  
  1986.     push mode
  1987.     call initgraph
  1988.  
  1989.     This procedure initializes the graphics system.  'mode'
  1990.     can be 0, 1, or 2, as follows:
  1991.  
  1992.     0       320x200x256     VGA lo-res graphics
  1993.     1       640x480x16      VGA hi-res graphics
  1994.     2       320x400x256     VGA med-res graphics
  1995.  
  1996.   ────────── closegraph         Close Graphics System
  1997.  
  1998.     This procedure closes the graphics system, and returns
  1999.     to the standard text mode.
  2000.  
  2001.   ────────── setgwin            Set Graphics Window
  2002.  
  2003.     push x1 y1
  2004.     push x2 y2
  2005.     call setgwin
  2006.  
  2007.     This procedure sets the graphics clipping window.
  2008.  
  2009.   ────────── cls                Clear Graphics Screen
  2010.  
  2011.     call cls
  2012.  
  2013.     This procedure clears the screen in graphics mode.
  2014.  
  2015.   ────────── clrgwin            Clear Graphics Window
  2016.  
  2017.     call clrgwin
  2018.  
  2019.     This procedure clears the current graphics window (using
  2020.     the current drawing color).
  2021.  
  2022.   ────────── setgcolor          Set Drawing Color
  2023.  
  2024.     push color
  2025.     call setgcolor
  2026.  
  2027.     This procedure sets the current drawing color.
  2028.  
  2029.   ────────── getgcolor          Get Drawing Color
  2030.  
  2031.     call getgcolor
  2032.     ; AX = current color
  2033.  
  2034.     This procedure returns the current drawing color.
  2035.  
  2036.   ────────── putpix             Put Pixel
  2037.  
  2038.     push x y
  2039.     call putpix
  2040.  
  2041.     This procedure puts a pixel at (x, y) in the current
  2042.     drawing color.  Output is clipped to the current window.
  2043.  
  2044.   ────────── getpix             Get Pixel
  2045.  
  2046.     push x y
  2047.     call getpix
  2048.     ; AX = color at (x, y)
  2049.  
  2050.     This procedure returns the color of the pixel at (x, y).
  2051.  
  2052.   ────────── putrow             Put Row of Pixels
  2053.  
  2054.     push x1 x2 y
  2055.     call putrow
  2056.  
  2057.     This procedure puts a row of pixels (basically like a
  2058.     horizontal line) from (x1, y) to (x2, y), in the current
  2059.     drawing color.
  2060.  
  2061.   ────────── line               Draw Line
  2062.  
  2063.     push x1 y1
  2064.     push x2 y2
  2065.     call line
  2066.  
  2067.     This procedure draws a line from (x1, y1) to (x2, y2) in
  2068.     the current drawing color.  Output is clipped to the
  2069.     current window.
  2070.  
  2071.   ────────── rect               Draw Rectangle
  2072.  
  2073.     push x1 y1
  2074.     push x2 y2
  2075.     call rect
  2076.  
  2077.     This procedure draws a rectangle from (x1, y1) to
  2078.     (x2, y2) in the current drawing color.  Output is
  2079.     clipped to the current window.
  2080.  
  2081.   ────────── frect              Draw Filled Rectangle
  2082.  
  2083.     push x1 y1
  2084.     push x2 y2
  2085.     call frect
  2086.  
  2087.     This procedure draws a filled rectangle from (x1, y1)
  2088.     to (x2, y2) in the current drawing color.  Output is
  2089.     clipped to the current window.
  2090.  
  2091.   ────────── outstr             Output String
  2092.  
  2093.     push x y
  2094.     push offset string
  2095.     call outstr
  2096.  
  2097.     This procedure prints 'string' on the screen, starting
  2098.     at (x, y).  Output is clipped to the current window.
  2099.  
  2100.   ────────── getimage           Get Image
  2101.  
  2102.     push offset buffer
  2103.     push x1 y1
  2104.     push x2 y2
  2105.     call getimage
  2106.  
  2107.     This procedure captures a rectangular block of pixels
  2108.     into 'buffer'.  No clipping is performed.
  2109.  
  2110.   ────────── putimage           Put Image
  2111.  
  2112.     push offset buffer
  2113.     push x1 y1
  2114.     call putimage
  2115.  
  2116.     This procedure displays a rectangular block of pixels
  2117.     from 'buffer' at (x1, y1).  Output is clipped to the
  2118.     current window.
  2119.  
  2120.   ────────── circle             Draw Circle
  2121.  
  2122.     push x y rad
  2123.     call circle
  2124.  
  2125.     This procedure draws a circle with center (x, y) and
  2126.     radius 'rad'.  Output is clipped to the current window.
  2127.  
  2128.     The radius specifies the Y radius.  The actual X radius
  2129.     may be different to compensate for the aspect ratio.
  2130.  
  2131.   ────────── ellipse            Draw Ellipse
  2132.  
  2133.     push x y xr yr
  2134.     call ellipse
  2135.  
  2136.     This procedure draws an ellipse with center (x, y) and
  2137.     radii 'xr' and 'yr'.  Output is clipped to the current
  2138.     window.
  2139.  
  2140.   ────────── fcircle            Draw Filled Circle
  2141.  
  2142.     push x y rad
  2143.     call fcircle
  2144.  
  2145.     This procedure draws a filled circle with center (x, y)
  2146.     and radius 'rad'.  Output is clipped to the current
  2147.     window.
  2148.  
  2149.     The radius specifies the Y radius.  The actual X radius
  2150.     may be different to compensate for the aspect ratio.
  2151.  
  2152.   ────────── fellipse           Draw Filled Ellipse
  2153.  
  2154.     push x y xr yr
  2155.     call fellipse
  2156.  
  2157.     This procedure draws a filled ellipse with center (x, y)
  2158.     and radii 'xr' and 'yr'.  Output is clipped to the
  2159.     current window.
  2160.  
  2161.   ────────── triangle           Draw Triangle
  2162.  
  2163.     push x1 y1
  2164.     push x2 y2
  2165.     push x3 y3
  2166.     call triangle
  2167.  
  2168.     This procedure draws a filled triangle with corners at
  2169.     (x1, y1), (x2, y2), and (x3, y3).  Output is clipped to
  2170.     the current window.
  2171.  
  2172.  
  2173. 7.  List of contributors (credits).
  2174.  
  2175.     Author:     Tenie Remmel.
  2176.  
  2177.     Major contributors:
  2178.  
  2179.       Tylisha C. Andersen -- VGA graphics library
  2180.  
  2181.     Minor contributors:
  2182.  
  2183.       Russell Leidich -- algorithm in 'truerand'
  2184.       Mark J. Restifo -- found redirection bug
  2185.       David Deganchi -- suggested fix for fgetc bug
  2186.  
  2187.  
  2188. 8.  History of changes.
  2189.  
  2190.   ────────── Version 1.1 Bug Fixes
  2191.  
  2192.     A bug in the 'STDIO' output was fixed.  It used Int 29h,
  2193.     which does not allow redirection.  Int 21h is being used
  2194.     instead.  This was pointed out by Mark J. Restifo.
  2195.  
  2196.     The documentation did not describe the increased-variety
  2197.     colorset used in  High-Res Text Mode.   A list of colors
  2198.     has been added.
  2199.  
  2200.     The random number code had a lot of problems.  Fixed.
  2201.  
  2202.     The procedure  'allocmem' would not allocate the largest
  2203.     block as returned from 'getmfree'.  Fixed.
  2204.  
  2205.     The procedure 'fgets' would crash, because it pushed the
  2206.     wrong number of arguments in calling 'fgetc'.  Fixed.
  2207.  
  2208.     If a file read crossed a buffer boundary, and writes had
  2209.     occurred to the buffer,  the buffer would  be discarded.
  2210.     This was due to the fgetc bug.  Fixed.
  2211.  
  2212.  
  2213.   ────────── Version 1.1 Additions
  2214.  
  2215.     A set of integrated graphics procedures  (using VGA) was
  2216.     added.   They use the  320x200x256, 320x400x256, and the
  2217.     640x480x16 modes.   The graphics procedures were written
  2218.     by Tylisha C. Andersen.
  2219.  
  2220.     Many of the routines  now have an 80386 version.   These
  2221.     are in the files '386LIB?.ASX'.  And yes, they have been
  2222.     optimized for the 80386, not just translated to 32-bit.
  2223.  
  2224.     Several example programs  have been added.   See section
  2225.     10 for more information.
  2226.  
  2227.     Another file access mode (mode 4) has been added.   This
  2228.     mode fails if the file exists.   This is useful when the
  2229.     file must not already exist,  for example using multiple
  2230.     temporary files.  Also, the file routines were optimized
  2231.     and fixed up  (i.e. fixed the fgetc bug).   The speed of
  2232.     the file read routines has been doubled.
  2233.  
  2234.  
  2235.   ────────── Version 2.0 Additions
  2236.  
  2237.     Bit-oriented file  procedures were added.   These can be
  2238.     useful for compression and encryption programs.  Now can
  2239.     anyone contribute some compression routines?
  2240.  
  2241.     A true random number procedure has been added.   This is
  2242.     not a pseudo-random RNG, this one works by reading timer
  2243.     countdown bits.   See the reference entry 'truerand' for
  2244.     more information.
  2245.  
  2246.     CRC routines  have been added for both 16 and 32-bit CRC
  2247.     values.   These routines are not table based.
  2248.  
  2249.     DOS version checking  has been added.   Now, the startup
  2250.     code checks to make sure DOS v4.0 is running.
  2251.  
  2252.     Trigonometric procedures  (sine, cosine, etc.) have been
  2253.     added.   These work on fixed-point numbers.   The method
  2254.     used is Taylor-series (slow, but very accurate).
  2255.  
  2256.  
  2257. 9.  Future additions, bug reporting, etc.
  2258.  
  2259.   Bugs may be reported to the author at:  tjr19@mail.nwlink.com.
  2260.  
  2261.   In the future, a set of wrapper procedures for calling
  2262.   some of the FREELIB routines from 'C' may be provided.
  2263.  
  2264.   This is a list of the routines wanted for future addition:
  2265.  
  2266.     (1) EMS/XMS/Disk virtual memory manager.  Should be
  2267.         transparent as to which medium is being used.
  2268.  
  2269.     (2) VGA graphics mode mouse routines to go with the VGA
  2270.         graphics code.  (16 AND 256 color mode)
  2271.  
  2272.     (3) General data compression: deflate, etc.
  2273.  
  2274.     (4) Low-level disk routines (read/write sector, format
  2275.         floppy).
  2276.  
  2277.     (5) Routines to read and write configuration data from
  2278.         the program's executable file.
  2279.  
  2280.     (6) Inter-procedure jumps, like the 'C' setjmp()/longjmp().
  2281.  
  2282.     (7) Sound card interface routines.
  2283.  
  2284.     (8) Indefinite long arithmetic, 256 bytes at least.
  2285.  
  2286.     (9) Process management and multitasking.
  2287.  
  2288.     (10) Anything else that might be useful!!!
  2289.  
  2290.  
  2291. 10.  Description of examples.
  2292.  
  2293.     Several example programs have been provided to demonstrate
  2294.     the capabilities of FREELIB:
  2295.  
  2296.     3XP1            Solves 3X+1 problem.  Demonstrates long integer
  2297.                     arithmetic and numeric output.
  2298.  
  2299.     BIN2HEX         Binary to hexadecimal filter.
  2300.  
  2301.     GRTEST          Simple demo of graphics system, random numbers.
  2302.  
  2303.     HEX2BIN         Hexadecimal to binary filter.
  2304.  
  2305.     SHOWGY          Program to display *.GY files  (16K grayscale).
  2306.                     Does resolution enhancement to 320x200.  Two of
  2307.                     these files are included (FACE.GY, ROSE.GY).
  2308.  
  2309.     SQUASH          Simple executable file compressor,  but it only
  2310.                     works with .COM files.
  2311.  
  2312.     VIEW            File viewer.  Demonstrates Hi-Res Text Mode and
  2313.                     the buffered file-access facilities.  Also uses
  2314.                     memory allocation.
  2315.  
  2316.     ZE, ZD          UUencode replacement, expands files by only 26%
  2317.                     instead of 40% like UUencode does.  ZE encodes,
  2318.                     and ZD decodes.
  2319.  
  2320.  
  2321.     These files can be found in the directory 'PROGS'.  To assemble
  2322.     the example programs, a batch file (REDO_EX.BAT) is provided.
  2323.  
  2324. ──────────────────────────────────────────────────────────────────────
  2325. ──────────────────────────────────────────────────────────────────────
  2326.